﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

namespace WindowsPhoneTicTacToe
{
    public partial class Gameboard : PhoneApplicationPage
    {

        #region Properties and Variables

        /// <summary>
        /// Multidimensional array to hold 3x3=9 TicTacToeButtons and their states
        /// </summary>
        public TicTacToeButton[,] GameboardArray { get; set; }

        /// <summary>
        /// Indicates current move, if IsCross == true, then next tictactoe button will become a cross
        /// if IsCross == false, then next tictactoe button will become a nought
        /// </summary>
        private bool _IsCross;
        public bool IsCross
        {
            get
            {
                return _IsCross;
            }
            set
            {
                tbStatus.Text = value ? "Player \"Crosses\" move" : "Player \"Noughts\" move";
                _IsCross = value;
            }
        }

        /// <summary>
        /// Indicates that the game is active
        /// </summary>
        private bool IsActive { get; set; }

        /// <summary>
        /// Indicates if current player is the winner of a game
        /// </summary>
        public bool IsWinner
        {
            get
            {
                return (CheckStraightLines() || CheckDiagonalLines());
            }
        }

        /// <summary>
        /// Indicates if the game is drawn
        /// </summary>
        public bool IsDrawn
        {
            get
            {
                return CheckIsDrawn();
            }
        }

        private TicTacToeButton[] winningCombinations = new TicTacToeButton[3];
        private Line winningLine = null;

        #endregion Properties and Variables

        #region Constructor

        public Gameboard()
        {
            InitializeGame();
        }

        #endregion Constructor

        #region Initialization

        private void InitializeGame()
        {
            InitializeComponent();
            SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;

            // create gameboard
            GameboardArray = new TicTacToeButton[3, 3];
            GameboardArray[0, 0] = ticTacToeButton1;
            GameboardArray[0, 1] = ticTacToeButton2;
            GameboardArray[0, 2] = ticTacToeButton3;
            GameboardArray[1, 0] = ticTacToeButton4;
            GameboardArray[1, 1] = ticTacToeButton5;
            GameboardArray[1, 2] = ticTacToeButton6;
            GameboardArray[2, 0] = ticTacToeButton7;
            GameboardArray[2, 1] = ticTacToeButton8;
            GameboardArray[2, 2] = ticTacToeButton9;

            gridGameboard.SetValue(Canvas.ZIndexProperty, 1);
            ticTacToeButton9.SetValue(Canvas.ZIndexProperty, 1);

            ticTacToeButton9.Background = new SolidColorBrush(Colors.White);

            Reset();
        }


        #endregion Initialization

        #region Methods

        private void DrawLine()
        {
            // should be exactly three buttons
            if (winningCombinations.Count() < 3)
                return;

            winningLine = new Line();

            Point startingPoint = GetCoordinatesOfElement(winningCombinations[0]);
            winningLine.X1 = startingPoint.X + (60 / 2); // 60 - height of TicTacToe button
            winningLine.Y1 = startingPoint.Y + (60 / 2) - 32; // 60 - width of TicTacToe button

            Point endPoint = GetCoordinatesOfElement(winningCombinations[2]);
            winningLine.X2 = endPoint.X + (60 / 2); // 60 - height of TicTacToe button
            winningLine.Y2 = endPoint.Y + (60 / 2) - 32; // 60 - width of TicTacToe button

            winningLine.Stroke = new SolidColorBrush(Colors.White);
            winningLine.StrokeThickness = 2;
            canvasGameboard.Children.Insert(0, winningLine);


        }

        /// <summary>
        /// Method to get XY coordinates of an element
        /// </summary>
        /// <param name="element">UI element to get XY coordinates from</param>
        /// <returns>Point representing XY coordinates</returns>
        private Point GetCoordinatesOfElement(UIElement element)
        {
            GeneralTransform gt = element.TransformToVisual(Application.Current.RootVisual as UIElement);
            Point pnt = gt.Transform(new Point(0, 0));
            // canvas location x=140, y=280
            pnt.X -= 140;
            pnt.Y -= 280;
            return pnt;
        }

        private bool CheckGameboard()
        {
            if (IsWinner)
            {
                // current player wins
                tbStatus.Text = string.Format("Player \"{0}\" won!", IsCross ? "Crosses" : "Noughts");
                DrawLine();
            }
            else if (IsDrawn)
            {
                tbStatus.Text = "Drawn!";
            }

            return (IsWinner || IsDrawn);
        }

        private bool CheckDiagonalLines()
        {
            bool diagonal1 = GameboardArray[0, 0].IsCross.HasValue && GameboardArray[0, 0].IsCross.Value == IsCross
                && GameboardArray[1, 1].IsCross.HasValue && GameboardArray[1, 1].IsCross.Value == IsCross
                && GameboardArray[2, 2].IsCross.HasValue && GameboardArray[2, 2].IsCross.Value == IsCross;

            bool diagonal2 = GameboardArray[0, 2].IsCross.HasValue && GameboardArray[0, 2].IsCross.Value == IsCross
                && GameboardArray[1, 1].IsCross.HasValue && GameboardArray[1, 1].IsCross.Value == IsCross
                && GameboardArray[2, 0].IsCross.HasValue && GameboardArray[2, 0].IsCross.Value == IsCross;

            // add winning combinations:
            if (diagonal1)
            {
                winningCombinations[0] = GameboardArray[0, 0];
                winningCombinations[1] = GameboardArray[1, 1];
                winningCombinations[2] = GameboardArray[2, 2];
            }
            else if (diagonal2)
            {
                winningCombinations[0] = GameboardArray[0, 2];
                winningCombinations[1] = GameboardArray[1, 1];
                winningCombinations[2] = GameboardArray[2, 0];
            }

            return (diagonal1 || diagonal2);

        }

        private bool CheckStraightLines()
        {
            return (CheckStraightLines(true) || CheckStraightLines(false));
        }

        private bool CheckStraightLines(bool isColumns)
        {

            bool result = false;

            winningCombinations = new TicTacToeButton[3];

            for (int x = 0; x < 3; x++)
            {
                for (int y = 0; y < 3; y++)
                {
                    if (isColumns)
                    {
                        // for columns
                        result = GameboardArray[y, x].IsCross.HasValue ? GameboardArray[y, x].IsCross.Value == IsCross : false;
                        winningCombinations[y] = GameboardArray[y, x];
                    }
                    else
                    {
                        // for rows
                        result = GameboardArray[x, y].IsCross.HasValue ? GameboardArray[x, y].IsCross.Value == IsCross : false;
                        winningCombinations[y] = GameboardArray[x, y];
                    }
                    if (!result)
                    {
                        // if at least one is false
                        break; // take next column or row
                    }
                }

                if (result)
                    return result;
            }

            return false;
        }

        private bool CheckIsDrawn()
        {
            for (int x = 0; x < 3; x++)
            {
                for (int y = 0; y < 3; y++)
                {
                    if (!GameboardArray[y, x].IsCross.HasValue)
                    {
                        return false;
                    }
                }
            }

            return true;
        }

        private void Reset()
        {
            ticTacToeButton1.IsCross = null;
            ticTacToeButton2.IsCross = null;
            ticTacToeButton3.IsCross = null;
            ticTacToeButton4.IsCross = null;
            ticTacToeButton5.IsCross = null;
            ticTacToeButton6.IsCross = null;
            ticTacToeButton7.IsCross = null;
            ticTacToeButton8.IsCross = null;
            ticTacToeButton9.IsCross = null;

            IsActive = true;
            tbStatus.Text = string.Empty;
            IsCross = true;
            if (winningLine != null)
            {
                canvasGameboard.Children.Remove(winningLine);
                winningLine = null;
            }

        }

        #endregion Methods

        #region Events

        void button_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (IsActive)
            {
                TicTacToeButton button = sender as TicTacToeButton;
                // if button haven't been pressed before
                if (button != null && !button.IsCross.HasValue)
                {
                    button.IsCross = IsCross;
                    if (!CheckGameboard())
                    {
                        // change visual state of a button
                        IsCross = !IsCross;
                    }
                    else
                    {
                        // game over
                        IsActive = false;
                    }
                }
            }
        }

        private void btnReplay_Click(object sender, RoutedEventArgs e)
        {
            Reset();
        }

        #endregion Events

    
    }
}